#ifndef STATUS_H_
#define STATUS_H_

#include <string>
#include <string.h>
#include <sstream>
#include <iostream>


#define ID_STR(ID,STR)          \
            case(ID):           \
                return(STR)
                

class DbStatus {

public:
	typedef enum {
		DB_CORRUPTION = 1000,
		DB_PARTITIONNOTFOUND,
		DB_KEYNOTFOUND,
		DB_SEGMENTNOTFOUND,
		DB_PARTIALREAD,
		DB_SEGMENTOVERFLOW,
        DB_INDEXARRAYOVERFLOW,
        DB_LOGOVERFLOW,
        DB_READONLY,
        DB_PARTITIONNOEXIST,
        DB_NOTSUPPORTED,
        DB_BUFFERWILLOVERFLOW
	}status_t;

	DbStatus()
    : m_status(0), 
      m_context(NULL) {    
    
    }

	DbStatus(const char* context, int status)
    : m_status(status),  
      m_context(copyContext(context)) {

	}

    DbStatus(const std::string& context, int status)
    : m_status(status),  
      m_context(copyContext(context.c_str())) {

    }


	inline DbStatus(const DbStatus& s)
    : m_status(s.m_status), 
      m_context(copyContext(s.m_context)) {   
	
	}

	inline DbStatus& operator=(const DbStatus& s) {
	
		if(&s == this) return *this;
        if(m_context) delete[] m_context;
		m_status = s.m_status; 
        m_context = copyContext(s.m_context);
	
        return *this;
    }

    ~DbStatus() {
        if(m_context) delete[] m_context;
        m_context = NULL;
    }
	
	bool isok() {
	
		return m_status == 0;
	}

	
	
	static std::string toString(int status) {
	
		if(status < 1000) return std::string(strerror(status));

		switch(status){
                ID_STR( DB_CORRUPTION, "corruption");
				ID_STR( DB_PARTITIONNOTFOUND, "partition not found");
				ID_STR( DB_SEGMENTNOTFOUND, "segment not found");
				ID_STR( DB_KEYNOTFOUND, "key not found");
				ID_STR( DB_PARTIALREAD, "partial read from db");
				ID_STR( DB_SEGMENTOVERFLOW, "reach the capacity of segment");
                ID_STR( DB_INDEXARRAYOVERFLOW, "indexarray over flow");
				ID_STR( DB_LOGOVERFLOW, "reach the capacity of log file");	
				ID_STR( DB_READONLY, "data store is readonly");
                ID_STR( DB_PARTITIONNOEXIST, "partition doesn't exist");
                ID_STR( DB_NOTSUPPORTED, "flag or operations are not supported yet");
                ID_STR( DB_BUFFERWILLOVERFLOW, "buffer is too small for IO reading");
                default: {
                
                    return "UNDEFINED ERROR";
                }
            }
	}

    std::string msg() {
	
        std::ostringstream oss;
		oss<<m_context<<":"<<m_status<<":"<<toString(m_status);
		return oss.str();
	}

	int getCode(){return (int)m_status;}

private:
	int m_status;
	const char* m_context;

private:
    static const char* copyContext(const char* ctx) {
        if(ctx) {
            char* buf = new char[strlen(ctx) + 1];
            strcpy(buf, ctx);
            return buf;
        }
        return NULL;
    }
};

#endif
